package cell

import (
	"github.com/treelab/updatecolumn/models"
)

// InstanceType of cell
func InstanceType() int32 {
	return models.Formula
}

  //#region Cell value convert
  cellValueToString({ column, cell }: IColumnAndCell) {
    // 如果formula的resultType不是DATE就返回cell.result
    if (column.resultType !== FormulaResultType.DATE) {
      return cell.result;
    }

    const format: string = getDatetimeFormat(column);
    return cell.result ? moment(new Date(cell.result)).format(format) : '';
  }

  cellValueToNumber({ cell }: IColumnAndCell) {
    const result = parseFloat(cell.result?.replace(/[^0-9.-]/g, ''));
    return isNaN(result) ? 0 : result;
  }

  cellValueToRating({ cell }: IColumnAndCell) {
    if (!_.isNaN(+cell.result)) {
      return Math.round(+cell.result);
    }
    return 0;
  }

  cellValueToDatetime({ cell }: IColumnAndCell) {
    return cell.result?.replace(/\s+/g, '').trim() ?? '';
  }

  cellValueToCheckbox({ cell }: IColumnAndCell) {
    return cell.result === 'true' || cell.result === 'checked';
  }

  cellValueToSelect({ column, cell }: IColumnAndCell) {
    let option;
    if (_.isString(cell.result)) {
      option = _.find(column.hasColumnOption.get(), i => _.trim(i.name) === _.trim(cell.result));
    } else if (_.isNumber(cell.result)) {
      option = _.find(column.hasColumnOption.get(), i => Number(i.name) === Number(cell.result));
    }
    return option;
  }

  cellValueToMultiSelect({ cell, column }: IColumnAndCell) {
    if (_.isString(cell.result)) {
      return _.filter(column.hasColumnOption.get(), i => _.trim(i.name) === _.trim(cell.result));
    } else if (_.isNumber(cell.result)) {
      return _.filter(column.hasColumnOption.get(), i => Number(i.name) === Number(cell.result));
    }
    return [];
  }
  //#endregion

  async convertCell(
    command: UpdateColumn_v2,
    o: CommonOptions,
    { columnCopy, referenceColumns }: { columnCopy: Column; referenceColumns?: Column[] },
  ) {
    const { column } = command;
    const { columnType: fromType } = columnCopy;
    // @ts-ignore
    const { formula, recordReferenceColumnId } = command.columnConfig as FormulaColumnConfig;
    const cells = column.hasCell.get();

    if (this.needEmptyCell(command)) {
      const fromCellHandle = this.instanceFactory.getCellInstance(fromType as ColumnType);
      fromCellHandle.emptyCells(command, cells, false, o);
    }

    const dependentColumnIds: string[] = _.map(column.hasDependentColumn.get(), (e: any) => e.uid);
    const dependentColumns: Column[] = await this.columnReadService.getColumnByIds(dependentColumnIds);

    const rows = await this.getRowData(command, o.txn);
    const events = new EventHelper();
    const visableNameMapping = new Map<string, string>();
    rows.forEach(row => {
      const result = FormulaExecutor.executeOnRow_v2(
        formula,
        row,
        dependentColumns,
        recordReferenceColumnId
          ? row.hasCell
              .get()
              .filter(
                (filterCell: any) =>
                  filterCell.columnId === recordReferenceColumnId || filterCell.columnId === column.uid,
              )
          : undefined,
      );
      const resultCell = result.cells[column.uid];
      let cell: Cell | undefined;
      if (resultCell?.length) {
        const _cell = result.cells[column.uid][0];
        cell = column.hasCell.get().find(c => c.uid === _cell.uid);
      }
      const action = {
        type: UpdateAction.SET_VALUE,
        value: {
          type: command.columnConfig.type,
          result: result.result,
        },
      };
      const updateCell: UpdateCell_v2 = {
        ...command,
        rowId: row.uid,
        action,
        _metadata: { ...command._metadata, source: Source.SAGA },
      };
      // 空行(formula依赖的cell为空)即直接返回;
      if (!cell && (result.result === 'undefined' || result.result === 'null' || !result.result)) {
        return;
      }
      // 如果当前行中formula列中cell为'undefined' 或 null，则清空，这里是undefined和null的原因是formula计算时直接return了
      if (cell && (cell.result === 'undefined' || cell.result === 'null' || !result.result)) {
        // WE DONT WANT TO EMPTY CELLS FOR CLEAN BRANCH
        // this.emptyCells(command, [cell!], true, o);
      } else {
        const rowData = this.upsertCell(cell, { command: updateCell }, { ...o, events }, { columnCopy });
        if (rowData) {
          visableNameMapping.set(rowData.uid, rowData.visibleName);
        }
      }
    });
    this.updateReferenceColumnAndDependencies({
      column,
      visableNameMapping,
      o,
      _metadata: command._metadata,
      referenceColumns,
    });
    o.events.bulkAddEvents(...events);
    return this;
  }

  async getRowData(command: UpdateColumn_v2, txn?: Txn): Promise<Row[]> {
    return await this.rowReadService.rowForFormula_v2(command.coreId, command.tableId, undefined, undefined, txn);
  }

  setCellValue({ cell, action }: ICCAction) {
    cell.result = (action.value as FormulaAndRollupCellValue).result?.toString();
    return this;
  }

  getCellValue(cell: Cell) {
    return cell.result;
  }

  emptyCells(command: UpdateColumn_v2, cells: readonly Cell[], deleteCells: boolean, o: CommonOptions) {
    if (!deleteCells) {
      _.forEach(cells, cell => {
        o.delQuads.push(...this.dgraphHelperService.getRemoveObjectQuads(cell.uid!, 'result'));
      });
    }
    super.emptyCells(command, cells, deleteCells, o);
    return this;
  }

